#include"downloadtablemodel.h"
#include"executor.h"
#include <iostream>
#include <QProgressBar>
#include <QSqlError>
#include <QSqlQuery>
#include <QSqlResult>
#include <QDir>
#include <QMutex>

QMutex modifyMutex;

void DownloadTableModel::addDownload(const QString &folder,
                                     const QString &fileName,
                                     const QString &URL,
                                     int priority)
{
    modifyMutex.lock();
    static QSqlQuery insertDownloadQuery("INSERT INTO downloads (Folder, Name, URL, Priority, Completed) VALUES (:f,:n,:u,:p,:c)");
    submitAll();
    insertDownloadQuery.bindValue("f", QVariant(folder));
    insertDownloadQuery.bindValue("n", QVariant(fileName));
    insertDownloadQuery.bindValue("u", QVariant(URL));
    insertDownloadQuery.bindValue("p", QVariant(priority));
    insertDownloadQuery.bindValue("c", QVariant(0));
    insertDownloadQuery.exec();
    insertDownloadQuery.finish();
    select();

    static QSqlQuery insertFolderQuery("UPDATE folder SET name = :n");
    insertFolderQuery.bindValue("n", QVariant(folder));
    insertFolderQuery.exec();
    insertFolderQuery.finish();

    static QSqlQuery selectMaxQuery("SELECT MAX(ID) FROM downloads");
    selectMaxQuery.exec();
    selectMaxQuery.next();
    emit addTask(selectMaxQuery.value(0).toInt(), folder + "/" + fileName, URL, priority);
    selectMaxQuery.finish();
    modifyMutex.unlock();
}

void DownloadTableModel::removeDownload(const QModelIndex &index)
{
    modifyMutex.lock();
    submitAll();
    emit removeTask(data(index).toInt());
    removeRow(index.row());
    submitAll();
    modifyMutex.unlock();
}

void DownloadTableModel::modify(int id, int column, QVariant value)
{
    modifyMutex.lock();
    if(!idToRow.contains(id)) rebuildCache();
    if(!idToRow.contains(id)) return;
    if(data(index(idToRow[id], 0)).toInt() != id) rebuildCache();
    setData(index(idToRow[id], column), value);
    modifyMutex.unlock();
}


DownloadTableModel::DownloadTableModel(QObject *parent, QSqlDatabase *db):QSqlRelationalTableModel(parent, *db)
{
    char const * const TABLENAME = "downloads";

    setEditStrategy(QSqlTableModel::OnManualSubmit);
    QSqlQuery query;
    if(!query.exec(QString("CREATE TABLE IF NOT EXISTS ") +
                   TABLENAME +
                   QString("(ID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, ") +
                   QString("Folder TEXT, ") +
                   QString("Name TEXT, ") +
                   QString("Priority INTEGER, ") +
                   QString("Completed INTEGER, ") +
                   QString("URL TEXT)"))){
        std::cerr << lastError().text().toStdString().c_str();
    }
    query.finish();
    setTable(TABLENAME);
    if(!select()){
        std::cerr << lastError().text().toStdString().c_str();
    }

    query.exec("CREATE TABLE IF NOT EXISTS folder(Name TEXT PRIMARY KEY)");
    query.exec("SELECT * FROM folder");
    if(!query.next()) query.exec(QString("INSERT INTO folder VALUES('") + QDir::homePath() + "')");

    query.finish();

    Executor *executor = new Executor(this);
    connect(this, SIGNAL(addTask(int,QString,QString,int)), executor, SLOT(submitTask(int,QString,QString,int)));
    connect(this, SIGNAL(removeTask(int)), executor, SLOT(cancelTask(int)));
}

void DownloadTableModel::rebuildCache()
{
    idToRow.clear();
    for(int row = 0; row < rowCount(); ++row){
        idToRow.insert(data(index(row, 0)).toInt(), row);
    }
}

